• Jump To … +
    main.js separate.js single.js web-apg-api.js main.js web-conv-api.js ast.js csv.js dangling-else.js display.js flags.js float.js limits.js main.js multiline-mode.js recursive.js replace.js rules.js split.js testonly.js trace.js udt.js unicode.js web-email.js word-boundaries.js main.js phone-number.js web-main.js web-phone-number.js main.js phone-number.js setup.js translate.js xml.js branch-fail-grammar.js main.js parent-mode-grammar.js setup.js universal-mode-grammar.js colors-app.js colors-callbacks.js colors.js main.js more-app.js more-setup.js more.js ast-callbacks.js bad-input.js basic.js ini-file.js main.js parser-callbacks.js setup.js trace.js anbncn.js and.js c-comment.js compound.js main.js nested.js not.js setup.js boundaries-grammar.js boundaries.js comment-grammar.js comment.js main.js negative-grammar.js negative.js positive-grammar.js positive.js setup.js main.js odata-grammar.js run.js setup.js area-code.js lookaround.js main.js phone-number.js setup.js simple.js all-operators.js default.js fancy-number.js limited-lines.js main.js select-operators.js select-rules.js setup.js main.js minimal.js parent-u.js parent.js phone-number.js setup.js stats.js trace.js universal-u.js universal.js callbacks.js grammar.js main.js parser.js writeHtml.js LICENSE.md README.md index.md
  • single.js

  • §
    /*  *************************************************************************************
     *   copyright: Copyright (c) 2021 Lowell D. Thomas, all rights reserved
     *     license: BSD-2-Clause (https://opensource.org/licenses/BSD-2-Clause)
     *   ********************************************************************************* */
  • §

    This example is a stripped down version of the main apg driver function.

    Note on teminology.

    APG is a parser generator. However, it really only generates a “grammar object” (see below) from the defining SABNF grammar. The generated parser is incomplete at this stage. Remaining, it is the job of the user to develop the generated parser from the grammar object and the APG Library (apg-lib).

    The following terminology my help clear up the confusion between the idea of a “generated parser” versus a “generated grammar object”.

    • The generating parser: APG is an APG parser (yes, there is a circular dependence between apg and apg-lib). We’ll call it the generating parser.
    • The target parser: APG’s goal is to generate a parser. We’ll call it the target parser.
    • The target grammar: this is the (ASCII) SABNF grammar defining the target parser.
    • The target grammar object: APG parses the SABNF grammar and generates the JavaScript source for a target grammar object.
    • The final target parser: The user then develops the final target parser using the generated target grammar object and the APG parsing library, apg-lib.
    module.exports = function single() {
      const write = require('../writeHtml');
      const apgJs = require('apg-js');
    
      function logErrors(api, header) {
        console.log('\n');
        console.log(`${header}:`);
        console.log(api.errorsToAscii());
        console.log('\nORIGINAL GRAMMAR:');
        console.log(api.linesToAscii());
      }
      try {
        const thisFileName = `${__filename}: `;
        const ApiCtor = apgJs.apgApi;
        const apglib = apgJs.apgLib;
    
        /* the SABNF grammar */
        let float = '';
        float += 'float    = [sign] decimal [exponent]\n';
        float += 'sign     = "+" / "-"\n';
        float += 'decimal  = integer [dot [fraction]]\n';
        float += '           / dot fraction\n';
        float += 'integer  = 1*%d48-57\n';
        float += 'dot      = "."\n';
        float += 'fraction = 1*%d48-57\n';
        float += 'exponent = "e" [esign] exp\n';
        float += 'esign    = "+" / "-"\n';
        float += 'exp      = 1*%d48-57\n';
    
        /* test complete generation in one step */
        const api = new ApiCtor(float);
        api.generate();
        if (api.errors.length) {
          logErrors(api, 'GRAMMAR ERRORS');
          console.log(api.displayAttributeErrors());
          throw new Error(`${thisFileName}grammar has errors`);
        }
    
        /* make a parser from the grammar object */
        const grammarObj = api.toObject();
  • §

    eslint-disable-next-line new-cap

        const parser = new apglib.parser();
        const result = parser.parse(grammarObj, 0, '123.0');
        let html = apglib.utils.parserResultToHtml(result, 'generated parser');
        html = apglib.utils.htmlToPage(html);
        write(html, 'single-step-parser');
      } catch (e) {
        let msg = 'EXCEPTION THROWN: ';
        if (e instanceof Error) {
          msg += `${e.name}: ${e.message}`;
        } else {
          msg += '\n';
          msg += require('node:util').inspect(e, {
            showHidden: true,
            depth: null,
            colors: true,
          });
        }
        console.log(msg);
      }
    };